/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package core.server;

import core.controller.MessageController;
import core.io.CodecFactory;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.executor.ExecutorFilter;
import org.apache.mina.filter.executor.OrderedThreadPoolExecutor;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;

/**
 *
 * @author Dung Pham
 */
public class GameServer {

    private MessageController messageHandler;
    private static GameServer instance = new GameServer();
    //private transient ServerInfo serverInfo = null;
    //// IwinServer data.
    private transient NioSocketAcceptor acceptor;
    private transient boolean isReady;
    private transient final Object lockSessionLevel;
    private transient OrderedThreadPoolExecutor workerService;
    private transient ScheduledExecutorService schedules;

    private GameServer() {
        this.lockSessionLevel = new Object();
        //// Apply mina framework.
//        loadResource();
    }

    private void initialize() {
        synchronized (lockSessionLevel) {
            this.acceptor = new NioSocketAcceptor(160);
            this.acceptor.setReuseAddress(true);
            this.acceptor.getSessionConfig().setReaderIdleTime(600);
            this.acceptor.getSessionConfig().setReceiveBufferSize(2048);
            DefaultIoFilterChainBuilder chain = this.acceptor.getFilterChain();
            this.acceptor.getSessionConfig().setTcpNoDelay(true);
            this.acceptor.getSessionConfig().setReadBufferSize(2048);

            //// Add a protocol codec filter.
            chain.addLast("codec", new ProtocolCodecFilter(new CodecFactory()));
            //if (ServerInfo.getInstance().isUsingExecutor()) {
            //this.workerService = Executors.newCachedThreadPool();
            this.workerService = new OrderedThreadPoolExecutor(0, 20000);
//                this.workerService = new OrderedThreadPoolExecutor();
            //chain.addLast("threadPoolEvents", new ExecutorFilter(this.workerService));
            chain.addLast("threadPoolEvents", new ExecutorFilter(this.workerService));
            //}
        }
    }

    /**
     * Synchronized session level. Start IwinServer.
     *
     * @return True if success.
     * @throws Throwable An exception can be thrown.
     */
    public boolean start() {
        synchronized (lockSessionLevel) {
            try {
                //// Start server by binding socket.
                if (!this.isReady) {
                    //this.startServerTime = new Date();
                    this.initialize();
                    //Reporter.infor("Get port :" + this.serverInfo.getServerPort());
                    messageHandler = new MessageController();
                    acceptor.setHandler(messageHandler);
                    acceptor.bind(new InetSocketAddress(9999));
//                    if (ServerInfo.getInstance().getBooleanAttribute(ServerInfo.IWIN_SERVER_MAINTENANCE_STATUS)) {
//                        return true;
//                    }
//                    Reporter.infor("Initialize schedules ....");
                    /*
                     * Init schedule pool for garbage collection
                     */
                    schedules = (ScheduledThreadPoolExecutor) Executors.newScheduledThreadPool(8);
//                    scheduleGC = (ScheduledFuture<?>) schedules.scheduleWithFixedDelay(new Runnable() {
//
//                        public void run() {
//                            ArrayList<IoSession> sessions = new ArrayList<IoSession>(acceptor.getManagedSessions().values());
//                            messageHandler.cleanUp(sessions);
//                        }
//                    }, 1, 1, TimeUnit.MINUTES);




//                    MonitorDatabase monitorDatabase = new MonitorDatabase();
//                    IwinThreadPool.getPool().runTask(monitorDatabase);

                    //loadSchedulePushMessage();
                    //loadScheduleLoginEvent();
                    //apiHttp = new MiniHttpServer(false, false);
                    //apiHttp.setEnvironmentPath(ServerRuntime.getCurrentDir());
                    //apiHttp.setPort(serverInfo.getServerAPIPort());
                    //apiHttp.setIpFilter(ActionHelper.getFilterIPAddress());
                    //apiHttp.setEnableAdminModule(true);
                    //apiHttp.start();
                    //Reporter.infor("Initialize multi-language.");
                    //IwinGlobals.getInstance();
//                    Reporter.infor("HTTP API is ready on " + serverInfo.getServerAPIPort());
//                    Reporter.infor("Listening on port " + this.serverInfo.getServerPort());
//                    Reporter.infor("IWin Server is ready.");
                    this.isReady = true;
                    return true;
                }

                return false;

            } catch (Exception ex) {
                //Reporter.error("Iwin server starting get exception :", ex);
                System.out.println("error: " + ex);
                return false;
            }
        }
    }

    public static void main(String[] args) {
//        System.out.println(IwinGlobals.getInstance(Locale.ENGLISH).
//                getResource(ServerSideMessage.DEFAULT_FILE_NAME).get(ServerSideMessage.WELCOME));
//        System.out.println(IwinGlobals.getInstance(IwinGlobals.VIETNAMESE_LOCALE).
//                getResource(ServerSideMessage.DEFAULT_FILE_NAME).get(ServerSideMessage.WELCOME));
//        System.out.println(IwinGlobals.getInstance(IwinGlobals.DEFAULT_LOCALE).
//                getResource(ServerSideMessage.DEFAULT_FILE_NAME).get(ServerSideMessage.WELCOME));
        if (!GameServer.instance.start()) {
            //Reporter.error("error on starting server");
            System.exit(1);
        }
    }
}
